home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / str.exe / STR.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-17  |  22.5 KB  |  870 lines

  1. //
  2. // str.cpp : str class implementation
  3. // Author  : Roy S. Woll
  4. //
  5. // Copyright (c) 1993 by Roy S. Woll
  6. // You may distribute this source freely as long as you leave all files
  7. // in their original form, including the copyright notice as is.
  8. //
  9. //
  10. // Version 2.11     3/17/93
  11. //    Friend operator ">>" changed to use str's buffer if > 256.
  12. //    Assign operator optimized to not copy referenced data.
  13. //    Fix - Remove member function now transfers only necessary characters
  14. //
  15. // Version 2.00     12/5/92
  16. //    Support searching/replacing, regular expressions, case sensitivity
  17. //
  18. //    Fixed the following bugs.
  19. //       1. Fixed size strings
  20. //       2. Concatenating a substr
  21. //
  22. //    Changed member functions pad/strip to modify instance, and introduced
  23. //    friend functions pad/strip.
  24. //
  25. // Version 1.00     10/20/92
  26. //
  27. #include <ctype.h>
  28. #include <string.h>
  29. #include <iostream.h>
  30. #include <iomanip.h>
  31. #include <assert.h>
  32.  
  33. #include "str.h"
  34. #include "dynstream.h"
  35.  
  36. int strnicmp(const char * s1, const char * s2, unsigned n);
  37. int stricmp(const char * s1, const char * s2);
  38. char * strlwr(char *);
  39. char * strupr(char *);
  40.  
  41. inline int min(int x, int y){if (x<y) return x; else return y;}
  42. inline int max(int x, int y){if (x>y) return x; else return y;}
  43.  
  44. // Define macro used to adjust internal debugging counters for object
  45. #ifdef DEBUG_STR     
  46. #define STR_SUB_COUNTERS(count)   count--;
  47. #define STR_ADD_COUNTERS(count)   count++;Total##count++;
  48. #else
  49. #define STR_SUB_COUNTERS(count)
  50. #define STR_ADD_COUNTERS(count)
  51. #endif
  52.  
  53.  
  54. static str::strdata NullData = {0, 0, 1, 0, 1, ""};
  55.  
  56. // Create and map to new buffer, and if previous buffer exists,
  57. //   transfer to new buffer.
  58. // Delete old buffer if unreferenced.
  59. char * str::getNewBuffer(int newbufsize){
  60.    return  getNewBuffer(length(), newbufsize);
  61. };
  62.  
  63. char * str::getNewBuffer(int len, int newbufsize)
  64. {
  65.    if (data==&NullData){
  66.      if (memsize_incr) newbufsize = max(newbufsize, memsize_init);
  67.      else newbufsize = memsize_init;
  68.    }
  69.    else {
  70.      if (!memsize_incr) return NULL;
  71.      if ((newbufsize>data->cursize) || (!newbufsize) )
  72.         newbufsize = max(newbufsize, data->cursize + memsize_incr);
  73.      else newbufsize = max(newbufsize, memsize_init);
  74.    }
  75.    if (!newbufsize) newbufsize = memsize_incr;       // don't allow 0 size
  76.  
  77.    strdata * newdata;
  78.    init(newdata, newbufsize, 0);
  79.    setNewBuffer(newdata, newbufsize, len);
  80.  
  81.    return data->buf;
  82. };
  83.  
  84. // Map to new buffer and if previous buffer exists, transfer to new buffer
  85. void str::setNewBuffer(strdata * newdata,
  86.            int newbufsize, int len){
  87.  
  88.    newdata->curlength = data->curlength;
  89.    newdata->strChange = data->strChange;
  90.  
  91.  
  92.    if (data->mystream) {
  93.  
  94.      // Use existing stream
  95.       newdata->mystream = data->mystream;
  96.  
  97.      // update existing stream to map to new buffer
  98.       newdata->mystream->rdbuf()->setNewBuffer(newdata->buf, newbufsize);
  99.  
  100.      // update stream length next time stream is called for previous data
  101.       if (!data->strChange){
  102.          data->strChange = 1;
  103.          data->curlength = data->mystream->rdbuf()->out_waiting();
  104.       };
  105.  
  106.      // force previous data to have unitialized stream
  107.       data->mystream = NULL;
  108.    };
  109.  
  110.    memcpy(newdata->buf, data->buf, len);
  111.  
  112.    if (!(--data->refcount)) {
  113.         delete data;
  114.         STR_SUB_COUNTERS(AllocationCount)
  115.    }
  116.  
  117.  
  118.    data = newdata;
  119. };
  120.  
  121.  
  122. void str::init(strdata*& adata, int cursize,
  123.           int curlength)
  124. {
  125.    STR_ADD_COUNTERS(AllocationCount)
  126.    if (!cursize) cursize=STR_DEFAULT_MEMINCR;
  127.  
  128.    adata =
  129.       (strdata *) new char [(cursize+1)+
  130.                             sizeof(strdata)-strdata::STR_DEBUG_BUFSIZE];
  131.    if (!adata){
  132.       cout << "Failed to allocate memory (" << cursize << ")" << endl;
  133.       assert(adata);
  134.    };
  135.  
  136.    adata->cursize=cursize;
  137.    adata->curlength=curlength;
  138.    adata->refcount=1;
  139.    adata->mystream=NULL;
  140.    adata->strChange=1;
  141. };
  142.  
  143.  
  144. // Construct an empty str
  145. str::str (void):
  146.           data(&NullData),
  147.           memsize_init(0), memsize_incr(STR_DEFAULT_MEMINCR),
  148.           flags(defaultFlags)
  149. {
  150.    STR_ADD_COUNTERS(ObjectCount)
  151.    data->refcount++;
  152. };
  153.  
  154. // Construct an empty str
  155. str::str (int p_bufsize, int p_incr):
  156.           data(&NullData),
  157.           memsize_init(p_bufsize), memsize_incr(p_incr),
  158.           flags(defaultFlags)
  159. {
  160.    STR_ADD_COUNTERS(ObjectCount)
  161.    data->refcount++;
  162. };
  163.  
  164.  
  165. // Construct a str containing substr, char *
  166. str::str (const char * s1, const char * s2):
  167.           memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
  168.           flags(defaultFlags)
  169. {
  170.  
  171.    STR_ADD_COUNTERS(ObjectCount)
  172.    int len1=(s1 ? strlen(s1) : 0);
  173.    int len2=(s2 ? strlen(s2) : 0);
  174.  
  175.    init(data, len1+len2, len1+len2);
  176.    memcpy(data->buf, s1, len1);
  177.    memcpy(data->buf+len1, s2, len2);
  178. };
  179.  
  180. // Construct a str containing char *, substr
  181. str::str (const char * s1, const substr& s2):
  182.           memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
  183.           flags(defaultFlags)
  184. {
  185.  
  186.    STR_ADD_COUNTERS(ObjectCount)
  187.    int len1=(s1 ? strlen(s1) : 0);
  188.    int len2=s2.length();
  189.  
  190.    init(data, len1+len2, len1+len2);
  191.    memcpy(data->buf, s1, len1);
  192.    memcpy(data->buf+len1, &s2.mystr->data->buf[s2.posReplace], len2);
  193. };
  194.  
  195. // Construct a str containing two char *
  196. str::str (const substr& s1, const char * s2):
  197.           memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
  198.           flags(defaultFlags)
  199. {
  200.  
  201.    STR_ADD_COUNTERS(ObjectCount)
  202.    int len1= s1.length();
  203.    int len2= (s2 ? strlen(s2) : 0);
  204.  
  205.    init(data, len1+len2, len1+len2);
  206.    memcpy(data->buf, &s1.mystr->data->buf[s1.posReplace], len1);
  207.    memcpy(data->buf+len1, s2, len2);
  208. };
  209.  
  210. // Construct a str containing two substr
  211. str::str (const substr& s1, const substr& s2):
  212.           memsize_init(0),memsize_incr(STR_DEFAULT_MEMINCR),
  213.           flags(defaultFlags)
  214. {
  215.  
  216.    STR_ADD_COUNTERS(ObjectCount)
  217.    int len1= s1.length();
  218.    int len2= s2.length();
  219.  
  220.    init(data, len1+len2, len1+len2);
  221.    memcpy(data->buf,      &s1.mystr->data->buf[s1.posReplace], len1);
  222.    memcpy(data->buf+len1, &s2.mystr->data->buf[s2.posReplace], len2);
  223. };
  224.  
  225. // Construct a str containing char *
  226. str::str (const char * s, int p_bufsize, int p_incr):
  227.           memsize_init(p_bufsize),memsize_incr(p_incr),
  228.           flags(defaultFlags)
  229. {
  230.    STR_ADD_COUNTERS(ObjectCount)
  231.    if (!s) return;
  232.  
  233.    int curlength, cursize;
  234.  
  235.    if (memsize_incr==0) {  // not allowed to expand
  236.       curlength = min(strlen(s), memsize_init);
  237.       cursize = memsize_init;
  238.    }
  239.    else {
  240.       curlength=strlen(s);
  241.       cursize = max(curlength, memsize_init);
  242.    };
  243.  
  244.    init(data, cursize, curlength);
  245.    memcpy(data->buf, s, curlength);
  246. };
  247.  
  248. // Construct a str containing str
  249. str::str (const str& s, int p_bufsize, int p_incr):
  250.           memsize_init(p_bufsize),memsize_incr(p_incr),
  251.           flags(defaultFlags)
  252. {
  253.    STR_ADD_COUNTERS(ObjectCount)
  254.  
  255.    if (memsize_incr) {
  256.       data = s.data;
  257.       data->refcount++;
  258.    }
  259.    else {
  260.       int curlength = min(s.length(), memsize_init);
  261.       init(data, memsize_init, curlength);
  262.       memcpy(data->buf, s, curlength);
  263.    };
  264.  
  265. };
  266.  
  267.  
  268. // Return a ostream that maps to the same buffer as the str
  269. ostream& str::stream(int pos){
  270.    return stream().seekp(pos);
  271. };
  272.  
  273. // Return a ostream that maps to the same buffer as the str
  274. ostream& str::stream(void){
  275.  
  276.   //
  277.   // check if need to allocate more memory
  278.   //
  279.    int allocsize=0;
  280.    if (data==&NullData) allocsize = memsize_init;    // first time allocating
  281.    else if (length()>=size()) allocsize = size()+memsize_incr;
  282.    _checkMemAllocation(allocsize);
  283.  
  284.   //
  285.   // Create stream if it doesn't exist
  286.   // otherwise tell dynstream about me in case it needs to extend buf
  287.   //
  288.    if (!data->mystream) data->mystream = new dynstream(this);
  289.    else data->mystream->rdbuf()->set_str(this);
  290.  
  291.  
  292.   //
  293.   // update stream length if length has been changed by str operators.
  294.   // Not done every time in case stream operation was the last operation 
  295.   // to change the length.
  296.   //
  297.    if (data->strChange) {
  298.        data->mystream->rdbuf()->set_len(data->curlength);
  299.        data->strChange=0;
  300.    };
  301.    return *data->mystream;
  302. };
  303.  
  304. int str::length(void) const{
  305.    if ((!data->strChange) && (data->mystream))
  306.       setlength(data->mystream->rdbuf()->out_waiting());
  307.  
  308.    return data->curlength;
  309. };
  310.  
  311. str::~str (void){
  312.    STR_SUB_COUNTERS(ObjectCount)
  313.  
  314.    if (!(--data->refcount)){
  315.       STR_SUB_COUNTERS(AllocationCount)
  316.  
  317.       delete data->mystream;
  318.       delete data;
  319.    };
  320. };
  321.  
  322. //
  323. // return (const char *)
  324. //
  325. str::operator const char * () const{
  326.    data->buf[length()] = 0;
  327.    return data->buf;
  328. };
  329.  
  330. const char * str::operator()(int index) const   
  331. {
  332.    return  (*this)() + index;
  333. }
  334.  
  335. char& str::operator[](int position)   // array indexing
  336. {
  337.    if (data->refcount>1) getNewBuffer(data->cursize);
  338.  
  339.    #ifndef SMART_STR_USER
  340.    //
  341.    // Force string to be null-terminated in case user
  342.    //   uses the "&" operator to pass a pointer (ie. &mystr[3])
  343.    //
  344.    if (!data->strChange) return *(char *)(*this)(position);
  345.          
  346.    #endif
  347.          
  348.    
  349.    return data->buf[position];
  350. }
  351.  
  352. int str::size(void) const{
  353.    return data->cursize;
  354. };
  355.                  
  356. //
  357. // str member = operators
  358. //
  359. str & str::_assign(const char * s, int len)
  360. {
  361.   // Get new buffer if necessary, but don't transfer contents.
  362.   // This is handled specially, so as to remove the unnecessary transfer.
  363.    if ((data->refcount>1) || (size()<len)) 
  364.       getNewBuffer( 0, max(size(),len) );
  365.  
  366.    if (!memsize_incr) len = min(len, size());
  367.    memcpy(data->buf, s, len);
  368.    setlength(len);
  369.    return *this;
  370.  
  371. };
  372.  
  373. str& str::operator = (const str& s){
  374.    if (this == &s) return *this;         // assignment to self
  375.    if (data == s.data) return *this;     // assignment to self
  376.  
  377.    if (!memsize_incr) return _assign(s, s.length());
  378.  
  379.    dynstream * prevStream=NULL;
  380.  
  381.    if (!(--data->refcount)) {  // deallocate old pointer
  382.       STR_SUB_COUNTERS(AllocationCount)
  383.  
  384.      //
  385.      // try to reuse this stream
  386.      //
  387.       prevStream = data->mystream;
  388.       if (s.data){
  389.          if (s.data->mystream) {
  390.             delete data->mystream;
  391.             prevStream = NULL;
  392.          }
  393.       }
  394.  
  395.       delete data;
  396.    };
  397.  
  398.    data = s.data;
  399.  
  400.    data->refcount++;
  401.  
  402.   //
  403.   // Map my stream to point to an existing stream using buffer data->buf
  404.   //
  405.    if (prevStream) {
  406.  
  407.          data->mystream = prevStream;  // what about previous mystream?
  408.  
  409.         //
  410.         // update s stream to map to new this stream
  411.         //
  412.          data->mystream->rdbuf()->setNewBuffer(data->buf, size());
  413.  
  414.         //
  415.         // update stream length next time stream is called for previous data
  416.         //
  417.          data->strChange = 1;
  418.  
  419.    }
  420.  
  421.  
  422.    return *this;
  423.  
  424. };
  425.  
  426.  
  427. str& str::operator = (const substr& s){
  428.    return _assign((*s.mystr)(s.posReplace), s.numReplace);
  429. };
  430.  
  431. str& str::operator = (const char * s){
  432.    return _assign(s, strlen(s));
  433. };
  434.  
  435. str& str::assign(const char * s, int len){
  436.    return _assign(s, min(strlen(s), len));
  437. };
  438.  
  439. str& str::operator = (const char s){
  440.    return _assign(&s, 1);
  441. };
  442.  
  443. str & str::_concat(const char * s, int len)
  444. {
  445.    int mylen = length();
  446.  
  447.    _checkMemAllocation(mylen + len);
  448.  
  449.    if (!memsize_incr) len = min(len, size()-mylen);
  450.    memcpy(data->buf + mylen, s, len);    //concat
  451.    setlength(mylen+len);
  452.    return *this;
  453.  
  454. };
  455.  
  456.  
  457. //
  458. // str member += operators
  459. //
  460. str & str::operator += (const str& s){
  461.    if (!length()) return *this=s;
  462.    return _concat(s, s.length());
  463. };
  464.  
  465. str & str::operator += (const substr& s){
  466.    return _concat(&s.mystr->data->buf[s.posReplace], s.length());
  467. };
  468.  
  469. str & str::operator += (const char * s){
  470.    return _concat(s, strlen(s));
  471. };
  472.  
  473. str & str::operator += (const char s){
  474.    return _concat(&s, 1);
  475. };
  476.  
  477.  
  478. //
  479. // str member << operators
  480. //
  481. str& str::operator << (const str& s)    { return *this+=s;};
  482. str& str::operator << (const substr& s) { return *this+=s;};
  483. str& str::operator << (const char * s)  { return *this+=s;};
  484. str& str::operator << (const char s)    { return *this+=s;};
  485. str& str::operator << (const int s){
  486.    stream() << s;
  487.    return *this;
  488. };
  489.  
  490. //
  491. // str member + operators
  492. //
  493. str str::operator+(const _SUBSTR & b) const{ return str(*this,b); };
  494. str str::operator+(const str&b)           const{ return str(*this,b); };
  495. str str::operator+(const char * b)        const{ return str(*this,b); };
  496. str str::operator+(const char b) const{
  497.    char buf[2];
  498.    buf[0]=b;
  499.    buf[1]=0;
  500.  
  501.    return str(*this,buf);
  502. };
  503.  
  504.  
  505. // 
  506. // istream/ostream friend functions
  507. //
  508. istream& operator >> (istream& stream, str & s){
  509.    if (s.memsize_init>256){   // Use str's current data buffer
  510.       s = " ";                // Gets new buffer if neccessary (ie. reference)
  511.       stream.getline(s.data->buf, s.size());
  512.       s.setlength(stream.gcount());
  513.       if (s[s.length()]==10)  // retrieve to end of line
  514.          s.setlength(s.length()-1);
  515.    }
  516.    else {
  517.       char buf[256];
  518.       stream.getline(buf, 256);
  519.       if (buf[stream.gcount()-1]==10)  // retrieve to end of line
  520.          buf[stream.gcount()-1]=0;
  521.  
  522.       s = buf;
  523.    };
  524.  
  525.    return stream;
  526. };
  527.  
  528. ostream& operator << (ostream& stream, const str & s){
  529.    return stream << s();
  530. };
  531.  
  532.  
  533. //
  534. // uppercase/lowercase friend functions
  535. //
  536. str uppercase(const char * s) {
  537.    str newstr(s);
  538.    strupr((char *)newstr());
  539.    return newstr;
  540. };
  541.  
  542. str lowercase(const char * s) {
  543.    str newstr(s);
  544.    strlwr((char *)newstr());
  545.    return newstr;
  546. };
  547.  
  548.  
  549. //
  550. // pad/strip
  551. //
  552. str& str::pad(int padsize, PadStripT t, char padchar){
  553.  
  554.    int len = length();
  555.  
  556.    if (len<padsize) {
  557.  
  558.       _checkMemAllocation(padsize);
  559.       if (!memsize_incr) padsize = min(padsize, size());
  560.       
  561.       if (t == right)
  562.          memset(&data->buf[len], padchar, padsize-len);
  563.  
  564.       else if (t == both){
  565.          int len1 = (padsize-len)/2;
  566.          int len2 = (padsize-len+1)/2;
  567.  
  568.          memmove(&data->buf[len1], &data->buf, len);
  569.          memset(&data->buf[0], padchar, len1);
  570.          memset(&data->buf[len+len1], padchar, len2);
  571.       }
  572.  
  573.       else{
  574.          int len1 = (padsize-len);
  575.  
  576.          memmove(&data->buf[len1], &data->buf, len);
  577.          memset(&data->buf[0], padchar, len1);
  578.       }
  579.  
  580.       setlength(padsize);
  581.    };
  582.  
  583.    return *this;
  584. }
  585.  
  586. str& str::strip(PadStripT t, char stripchar){
  587.  
  588.    int len = length();
  589.    int start = 0;
  590.    int end = len-1;
  591.  
  592.    if (end<0) return *this;
  593.  
  594.    if ((t == leading) || (t==both)){
  595.       for (; start<=end; start++)
  596.          if (data->buf[start] != stripchar) break;
  597.    };
  598.  
  599.    if ((t == trailing) || (t==both)){
  600.        if (data->buf[end] == stripchar) {
  601.           for (; end >= start; end--){
  602.              if (data->buf[end] != stripchar) break;
  603.           };
  604.        };
  605.    };
  606.  
  607.    if ((end-start+1)<len)
  608.    {
  609.       _checkMemAllocation();
  610.       if (start) memmove(&data->buf[0], &data->buf[start], end-start+1);
  611.       setlength(end-start+1);
  612.    };
  613.  
  614.    return *this;
  615.  
  616. };
  617.  
  618.  
  619. str& str::strip(PadStripT t, const char * stripchars){
  620.  
  621.    int len = length();
  622.    int start = 0;
  623.    int end = len-1;
  624.  
  625.    if (end<0) return *this;
  626.  
  627.  
  628.    if ((t == leading) || (t==both)){
  629.  
  630.       int pos = strspn((*this)(), stripchars);
  631.       if (pos>0) start += pos;
  632.  
  633.    };
  634.  
  635.    if ((t == trailing) || (t==both)){
  636.  
  637.      if (strchr(stripchars, data->buf[end])){
  638.         for (; end>=start; end--){
  639.            if (!strchr(stripchars, data->buf[end])) break;
  640.         }
  641.      }
  642.    };
  643.  
  644.    if ((end-start+1)<len)
  645.    {
  646.       _checkMemAllocation();
  647.       if (start) memmove(&data->buf[0], &data->buf[start], end-start+1);
  648.       setlength(end-start+1);
  649.    };
  650.  
  651.    return *this;
  652. };
  653.  
  654. str pad(str s, int padsize, str::PadStripT t, char padchar){
  655.    return s.pad(padsize, t, padchar);
  656. };
  657.  
  658. str strip(str s, str::PadStripT t, const char * stripchars){
  659.    return s.strip(t, stripchars);
  660. };
  661.  
  662. str strip(str s, str::PadStripT t, char stripchar){
  663.    return s.strip(t, stripchar);
  664. };
  665.  
  666.  
  667. //
  668. // insert/remove
  669. //
  670. int str::insert(int pos, char ch){
  671.     char tempstr[2];
  672.     tempstr[0] = ch;
  673.     tempstr[1] = 0;
  674.     return insert(pos, tempstr);
  675. }
  676.  
  677. int str::insert(int pos, const char * insertStr){
  678.    int len = length();
  679.    int afterPos = len+1-pos;  // number of characters following pos
  680.  
  681.    if (afterPos<0) return 0;  // out of range
  682.  
  683.    int insertLen = strlen(insertStr);
  684.    _checkMemAllocation( len+insertLen );
  685.  
  686.    if (!memsize_incr) insertLen = min(insertLen, size()-len);
  687.  
  688.    if (insertLen){
  689.      if (afterPos)
  690.         memmove(&data->buf[pos + insertLen], &data->buf[pos], afterPos);
  691.      memmove(&data->buf[pos], insertStr, insertLen);
  692.      setlength(len+insertLen);
  693.      return 1;
  694.    }
  695.    else return 0;
  696. };
  697.  
  698. void str::remove(int pos, int numdel){
  699.    int len = length();
  700.    if (pos>=len) return;
  701.    _checkMemAllocation();
  702.  
  703.    numdel = min(numdel, len-pos); 
  704.    memmove(&data->buf[pos], &data->buf[pos+numdel], len-(numdel+pos));
  705.    setlength(len-numdel);
  706. };   
  707.  
  708.  
  709. //
  710. // substr member operators/functions
  711. //
  712. _SUBSTR::substr(const str * data, int AposReplace, int AnumReplace):
  713.    mystr((str *)data), posReplace(AposReplace), numReplace(AnumReplace){};
  714.  
  715. _SUBSTR str::operator()(int pos, int numreplace)
  716. {
  717.    return substr(this, pos, numreplace);
  718. }
  719.  
  720. const _SUBSTR str::operator()(int pos, int numreplace) const
  721. {
  722.    return substr(this, pos, numreplace);
  723. }
  724.  
  725. int _SUBSTR::length(void) const{
  726.    return min(numReplace, max(0, mystr->length()-posReplace) );
  727. };
  728.  
  729.  
  730. str & _SUBSTR::operator = (const char * s){
  731.    if (posReplace<0) return *this->mystr;
  732.  
  733.    if (strlen(s)==length()){
  734.       mystr->_checkMemAllocation();
  735.       memcpy(&mystr->data->buf[posReplace], s, length());
  736.    }
  737.    else {
  738.       mystr->remove(posReplace, numReplace);
  739.       mystr->insert(posReplace, s);
  740.    };
  741.    return *this->mystr;
  742. };
  743.  
  744. str & _SUBSTR::operator = (const substr& s){
  745.    return *this = *s.mystr;
  746. };
  747.  
  748. str _SUBSTR::operator+(const char * s) const{
  749.    return str(*this, s);
  750. };
  751.  
  752. str _SUBSTR::operator+(const substr& s) const{
  753.    return str(*this, s);
  754. };
  755.  
  756. int _SUBSTR::compare(const char * s) const{
  757.    return mystr->strncmp((*this->mystr)(posReplace), s, numReplace);
  758. };
  759.  
  760. int _SUBSTR::compare(const substr& s) const{
  761.    int len = min(numReplace, s.numReplace);
  762.    return mystr->strncmp((*this->mystr)(posReplace), (*s.mystr)(s.posReplace), len);
  763. };
  764.  
  765. int _SUBSTR::operator==(const char *s) const{ return compare(s)==0; };
  766. int _SUBSTR::operator<=(const char *s) const{ return compare(s)<=0; };
  767. int _SUBSTR::operator>=(const char *s) const{ return compare(s)>=0; };
  768. int _SUBSTR::operator!=(const char *s) const{ return compare(s)!=0; };
  769. int _SUBSTR::operator< (const char *s) const{ return compare(s)< 0; };
  770. int _SUBSTR::operator> (const char *s) const{ return compare(s)> 0; };
  771.  
  772. int _SUBSTR::operator==(const substr& s) const{ return compare(s)==0; };
  773. int _SUBSTR::operator<=(const substr& s) const{ return compare(s)<=0; };
  774. int _SUBSTR::operator>=(const substr& s) const{ return compare(s)>=0; };
  775. int _SUBSTR::operator!=(const substr& s) const{ return compare(s)!=0; };
  776. int _SUBSTR::operator< (const substr& s) const{ return compare(s)< 0; };
  777. int _SUBSTR::operator> (const substr& s) const{ return compare(s)> 0; };
  778.  
  779. _SUBSTR::operator str() const{
  780.   str temp;
  781.   temp.assign((*(mystr))(posReplace), numReplace);
  782.   return temp;
  783. };
  784.  
  785. int str::_checkMemAllocation(int requiredLen){
  786.    if ((data->refcount<=1) && (size()>=requiredLen)) return 1;
  787.  
  788.    return (getNewBuffer(max(size(), requiredLen))!=NULL);
  789. };
  790.  
  791.  
  792. //
  793. // Case sensitivity member functions
  794. //
  795. int str::caseSensitive(void) const { return !(flags & ICASE); }
  796.  
  797. void str::setCaseSensitive(int val) 
  798.   if (val) flags &= !ICASE;
  799.   else flags |= ICASE; 
  800. }
  801.  
  802. void str::setdefaultCaseSensitive(int val)
  803. {
  804.   if (val) defaultFlags &= !ICASE;
  805.   else defaultFlags |= ICASE; 
  806. }
  807.  
  808. //
  809. // Friend/Global str relational operators
  810. //
  811. str operator + (const char *a, const str&b)        {  return str(a,b); };
  812. str operator + (const char *a, const _SUBSTR&b){  return str(a,b); };
  813.  
  814. int compare(const char * a, const str & b) {return ( b.strcmp(a, b) );};
  815. int compare(const str& a,   const str & b) {return ( a.strcmp(a, b) );};
  816. int compare(const str& a,  const char * b) {return ( a.strcmp(a, b) );};
  817.  
  818. int operator ==(const char *a, const str&b){return (compare(a,b) == 0); };
  819. int operator >=(const char *a, const str&b){return (compare(a,b) >= 0); };
  820. int operator <=(const char *a, const str&b){return (compare(a,b) <= 0); };
  821. int operator !=(const char *a, const str&b){return (compare(a,b) != 0); };
  822. int operator > (const char *a, const str&b){return (compare(a,b) > 0); };
  823. int operator < (const char *a, const str&b){return (compare(a,b) < 0);};
  824.  
  825. int operator ==(const char *a, const _SUBSTR &b){ return b==a; };
  826. int operator >=(const char *a, const _SUBSTR &b){ return b<=a; };
  827. int operator <=(const char *a, const _SUBSTR &b){ return b>=a; };
  828. int operator !=(const char *a, const _SUBSTR &b){ return b!=a; };
  829. int operator > (const char *a, const _SUBSTR &b){ return b<a;  };
  830. int operator < (const char *a, const _SUBSTR &b){ return b>a;  };
  831.  
  832. //
  833. // Member str relational operators
  834. //
  835. int str::operator==(const char *b) const{ return (compare(*this,b) == 0); };
  836. int str::operator<=(const char *b) const{ return (compare(*this,b) <= 0); };
  837. int str::operator>=(const char *b) const{ return (compare(*this,b) >= 0); };
  838. int str::operator!=(const char *b) const{ return (compare(*this,b) != 0); };
  839. int str::operator> (const char *b) const{ return (compare(*this,b) > 0); };
  840. int str::operator< (const char *b) const{ return (compare(*this,b) < 0); };
  841.  
  842. int str::operator==(const str &b) const{ return (compare(*this,b) == 0); };
  843. int str::operator<=(const str &b) const{ return (compare(*this,b) <= 0); };
  844. int str::operator>=(const str &b) const{ return (compare(*this,b) >= 0); };
  845. int str::operator!=(const str &b) const{ return (compare(*this,b) != 0); };
  846. int str::operator> (const str &b) const{ return (compare(*this,b) > 0); };
  847. int str::operator< (const str &b) const{ return (compare(*this,b) < 0); };
  848.  
  849.  
  850. int str::strncmp(const char * s1, const char * s2, int n) const{
  851.    if (caseSensitive()) return ::strncmp(s1,s2,n);
  852.    else return ::strnicmp(s1,s2,n);
  853. };
  854.  
  855. int str::strcmp(const char * s1, const char * s2) const{
  856.    if (caseSensitive()) return ::strcmp(s1,s2);
  857.    else return ::stricmp(s1,s2);
  858. };
  859.  
  860. int str::defaultFlags = 0;
  861.  
  862. #ifdef DEBUG_STR
  863. int str::dynstreamCount=0;
  864. int str::ObjectCount=0;
  865. int str::AllocationCount=0;
  866. int str::TotalObjectCount=0;
  867. int str::TotalAllocationCount=0;
  868. #endif
  869.